/*
 * 文件名：LoginInterceptor.java
 * 版权：Copyright by 联通系统集成有限公司
 * 描述：
 * 修改人：焦凯旋
 * 修改时间：2019年6月21日
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */

package com.bicycle.platform.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bicycle.common.entity.base.Message;
import com.bicycle.common.enums.CommonBusinessCodeEnum;
import com.bicycle.common.enums.PermissionBusinessCodeEnum;
import com.bicycle.common.helper.IPAddressHelper;
import com.bicycle.common.helper.RedisStringHelper;
import com.bicycle.common.helper.SignatureHelper;
import com.bicycle.service.vo.BicycleSystemUserLoginVo;
import com.bicycle.platform.constant.Constants;
import com.bicycle.service.entity.BicycleSystemMenu;
import com.bicycle.service.entity.BicycleSystemOperationLog;
import com.bicycle.service.entity.BicycleSystemRoleMenu;
import com.bicycle.service.service.IBicycleSystemMenuService;
import com.bicycle.service.service.IBicycleSystemOperationLogService;
import com.bicycle.service.service.IBicycleSystemRoleMenuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Configuration
public class LoginInterceptor extends HandlerInterceptorAdapter {

	@Autowired
	private IBicycleSystemMenuService bicycleSystemMenuService;
	@Autowired
	private IBicycleSystemRoleMenuService bicycleSystemRoleMenuService;
	@Autowired
	private IBicycleSystemOperationLogService bicycleSystemOperationLogService;
	@Autowired
	private RedisStringHelper redisStringHelper;
	@Autowired
	private Environment environment;

	@SuppressWarnings("unchecked")
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		// 验证token信息
		// String token = request.getHeader(Constants.TOKEN_KEY);
		String token = (String) request.getSession().getAttribute(Constants.BICYCLE_SESSION_LOGIN_TOKEN);
		if (StringUtils.isBlank(token)) {
			Message message = new Message();
			message.setCode(PermissionBusinessCodeEnum.CODE_INFO_LOGIN_EXPIRE_ERROR.getKey());
			message.setMessage(PermissionBusinessCodeEnum.CODE_INFO_LOGIN_EXPIRE_ERROR.getValue());
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/json; charset=utf-8");
			response.getWriter().write(JSON.toJSONString(message));
			return false;
		}

		BicycleSystemUserLoginVo userLoginResp = JSON.parseObject(redisStringHelper.get(Constants.BICYCLE_TOKEN_LOGIN_USER + token), BicycleSystemUserLoginVo.class);
		if (userLoginResp == null) {
			Message message = new Message();
			message.setCode(PermissionBusinessCodeEnum.CODE_INFO_LOGIN_EXPIRE_ERROR.getKey());
			message.setMessage(PermissionBusinessCodeEnum.CODE_INFO_LOGIN_EXPIRE_ERROR.getValue());
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/json; charset=utf-8");
			response.getWriter().write(JSON.toJSONString(message));
			return false;
		}

		String cacheToken = redisStringHelper.get(Constants.BICYCLE_ACCOUNT_LOGIN_USER + userLoginResp.getAccount());
		if (StringUtils.isBlank(cacheToken)) {
			Message message = new Message();
			message.setCode(PermissionBusinessCodeEnum.CODE_INFO_LOGIN_EXPIRE_ERROR.getKey());
			message.setMessage(PermissionBusinessCodeEnum.CODE_INFO_LOGIN_EXPIRE_ERROR.getValue());
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/json; charset=utf-8");
			response.getWriter().write(JSON.toJSONString(message));
			return false;
		}

		// 验证token是当前登录账户
		if (!StringUtils.equals(cacheToken, token)) {
			Message message = new Message();
			message.setCode(PermissionBusinessCodeEnum.CODE_INFO_LOGIN_TOKEN_ERROR.getKey());
			message.setMessage(PermissionBusinessCodeEnum.CODE_INFO_LOGIN_TOKEN_ERROR.getValue());
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/json; charset=utf-8");
			response.getWriter().write(JSON.toJSONString(message));
			return false;
		}
		// 每次访问都重置一下失效时间
		int tokenExpires = StringUtils.isNotEmpty(environment.getProperty("session.expires.time")) ? Integer.parseInt(environment.getProperty("session.expires.time")) : 1800;
		// 存取token信息
		redisStringHelper.set(Constants.BICYCLE_TOKEN_LOGIN_USER + token, JSON.toJSONString(userLoginResp));
		redisStringHelper.expire(Constants.BICYCLE_TOKEN_LOGIN_USER + token, tokenExpires);

		// 将登录用户绑定token
		redisStringHelper.set(Constants.BICYCLE_ACCOUNT_LOGIN_USER + userLoginResp.getAccount(), token);
		redisStringHelper.expire(Constants.BICYCLE_ACCOUNT_LOGIN_USER + userLoginResp.getAccount(), tokenExpires);

		StringBuffer buffer = new StringBuffer();

		// api 验证开关
		int apiValidateSwitch = StringUtils.isNoneBlank(environment.getProperty("api.validate.switch")) ? Integer.parseInt(environment.getProperty("api.validate.switch")) : 1;
		if (apiValidateSwitch == 1) {
			// 校验签名
			Map<String, Object> parameters = new HashMap<String, Object>();
			if (StringUtils.equalsIgnoreCase(request.getMethod(), "GET")) {
				// GET方法
				Map<String, String[]> map = request.getParameterMap();
				for (String key : map.keySet()) {
					parameters.put(key, map.get(key)[0]);
				}
			} else if (StringUtils.equalsIgnoreCase(request.getMethod(), "POST")) {
				// POST方法
				if (StringUtils.contains(request.getContentType(), "application/json")) {
					// json格式
					InputStream inputStream = request.getInputStream();
					BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
					String line;
					while ((line = in.readLine()) != null)
						buffer.append(line + "\n");
					log.info(">>>>>>获取json数据:{}", buffer.toString());
					JSONObject jsonObject = JSON.parseObject(buffer.toString());
					for (String key : jsonObject.keySet()) {
						parameters.put(key, jsonObject.getString(key));
					}
				} else {
					Map<String, String[]> map = request.getParameterMap();
					for (String key : map.keySet()) {
						parameters.put(key, map.get(key)[0]);
					}
				}
			}
			if (!SignatureHelper.isSignatureValid(parameters, environment.getProperty("api.secret"))) {
				Message message = new Message();
				message.setCode(CommonBusinessCodeEnum.CODE_SIGN_ERROR.getKey());
				message.setMessage(CommonBusinessCodeEnum.CODE_SIGN_ERROR.getValue());
				response.setCharacterEncoding("UTF-8");
				response.setContentType("application/json; charset=utf-8");
				response.getWriter().write(JSON.toJSONString(message));
				return false;
			}
		}

		String servletPath = request.getServletPath();

		BicycleSystemMenu bicycleSystemMenu = bicycleSystemMenuService.getOne(new QueryWrapper<BicycleSystemMenu>(BicycleSystemMenu.builder().url(servletPath).state(1).build()),false);
		if (bicycleSystemMenu == null) {
			// 匹配不到菜单 暂时通过
			// Message message = new Message();
			// message.setCode(PermissionBusinessCodeEnum.CODE_INFO_ACCOUNT_PERMISSION_ERROR.getKey());
			// message.setMessage(PermissionBusinessCodeEnum.CODE_INFO_ACCOUNT_PERMISSION_ERROR.getValue());
			// response.setCharacterEncoding("UTF-8");
			// response.setContentType("application/json; charset=utf-8");
			// response.getWriter().write(JSON.toJSONString(message));
			// return false;
			return true;
		}
		BicycleSystemRoleMenu bicycleSystemRoleMenu = bicycleSystemRoleMenuService.getOne(new QueryWrapper<BicycleSystemRoleMenu>(BicycleSystemRoleMenu.builder().roleId(userLoginResp.getRoleId()).menuId(bicycleSystemMenu.getMenuId()).build()));
		if (bicycleSystemRoleMenu == null) {
			// 账户无权限
			Message message = new Message();
			message.setCode(PermissionBusinessCodeEnum.CODE_INFO_ACCOUNT_PERMISSION_ERROR.getKey());
			message.setMessage(PermissionBusinessCodeEnum.CODE_INFO_ACCOUNT_PERMISSION_ERROR.getValue());
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/json; charset=utf-8");
			response.getWriter().write(JSON.toJSONString(message));
			return false;
		}
		BicycleSystemOperationLog bicycleSystemOperationLog = new BicycleSystemOperationLog();
		bicycleSystemOperationLog.setAccount(userLoginResp.getAccount());
		bicycleSystemOperationLog.setSysUserId(userLoginResp.getSysUserId());
		bicycleSystemOperationLog.setUrl(servletPath);
		bicycleSystemOperationLog.setIp(IPAddressHelper.getIpAddress(request));
		bicycleSystemOperationLog.setMenu(bicycleSystemMenu.getMenuName());
		bicycleSystemOperationLog.setCreateTime(new Date());
		bicycleSystemOperationLog.setOperateDesc(bicycleSystemMenu.getMenuDesc());
		bicycleSystemOperationLog.setDataStruts(buffer.toString());
		bicycleSystemOperationLogService.save(bicycleSystemOperationLog);
		return true;
	}
}
